package com.nettyBasic.n3_channel;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.Scanner;

/**
 * @author： pang-yun
 * @date： 2021-09-11 16:33
 * 功能目的 ：用于  当channel  关闭以后  还希望能进行一些其他操作
 * <p>
 * 但是  channel.close  是异步处理关闭   两个线程 下  main  会直接执行 关闭后的某些处理  而不会真正的等待线程关闭之后在去执行
 * 为此  我们要从 channelFuture 中 获取 closeFuture 对象 来执行这项任务
 * - 可以sync  来进行同步关闭处理
 * - 也可以  addListener() 来进行 异步处理  当channel 关闭之后 回调
 * <p>
 * <p>
 * 主要解决的是： channel.close 之后  发现此程序并未停止   因为  NioSocketChannel 中还有一些线程需要进行关闭
 *              closeFuture.ShutDownGraceFully()
 */
@Slf4j
public class CloseFutureClient {
    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        ChannelFuture channelFuture = new Bootstrap()
                .group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                .handler(
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                                nioSocketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                                nioSocketChannel.pipeline().addLast(new StringEncoder());
                            }
                        }
                ).connect(new InetSocketAddress(9999));
        Channel channel = channelFuture.sync().channel();

        new Thread(() -> {
            Scanner scanner = new Scanner(System.in);
            while (true) {
                String s = scanner.nextLine();
                if ("quit".equals(s)) {
                    channel.close();  // 异步处理关闭
                    break;
                }
                channel.writeAndFlush(s);
            }
        }, "Client").start();

        // 获取closeFuture 对象   1.同步处理关闭    2.异步处理关闭
        ChannelFuture closeFuture = channel.closeFuture();
       /* closeFuture.sync();
        log.info("closed...");*/

        //---------异步处理关闭---
        closeFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                log.info("close之后进行.......");
                eventLoopGroup.shutdownGracefully();  // 优雅的停止 eventLoopGroup 先不接受任务  然后将 手中任务执行完毕后关闭
            }
        });
    }
}
